package cn.zero.service.impl;

import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.zero.config.AppConstants;
import cn.zero.model.User;
import cn.zero.model.Wallet;
import cn.zero.repository.WalletRepository;
import cn.zero.repository.UserRepository;
import cn.zero.service.WalletService;
import cn.zero.util.RSAUtil;
import cn.zero.service.UserService;

@Service("userService")
public class UserServiceImpl implements UserService {

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private WalletRepository walletRepository;

	@Autowired
	private WalletService walletService;

	@Override
	@Transactional(readOnly = true)
	public User get(String mobile) {
		return userRepository.getByMobile(mobile);
	}

	@Override
	@Transactional
	public User create(String mobile, String password, Long invitorId) {
		if (existMobile(mobile)) {
			throw new RuntimeException("手机号码已经存在!");
		}
		User user = userRepository.save(new User(mobile, password, invitorId));
		Map<String, byte[]> keyMap = RSAUtil.generateKeyBytes();
		Wallet wallet = new Wallet();
		wallet.setPrivateKey(Base64.encodeBase64String(keyMap.get(RSAUtil.PRIVATE_KEY)));
		wallet.setPublicKey(Base64.encodeBase64String(keyMap.get(RSAUtil.PUBLIC_KEY)));
		wallet.setUserId(user.getId());
		walletRepository.save(wallet);
		if (AppConstants.BALANCE > AppConstants.FRIST_SIGN_UP_PRIZE_AMOUNT) {
			walletService.change(user.getId(), AppConstants.FRIST_SIGN_UP_PRIZE_AMOUNT,
					"注册奖励: " + AppConstants.FRIST_SIGN_UP_PRIZE_AMOUNT);
			if (AppConstants.BALANCE > AppConstants.INVITE_SIGN_UP_PRIZE_AMOUNT) {
				walletService.change(invitorId, AppConstants.INVITE_SIGN_UP_PRIZE_AMOUNT, "邀请注册奖励: " + AppConstants.INVITE_SIGN_UP_PRIZE_AMOUNT);
			}
		}
		return user;
	}

	@Override
	@Transactional(readOnly = true)
	public boolean existMobile(String mobile) {
		return userRepository.count(new Specification<User>() {

			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				return cb.equal(root.get("mobile"), mobile);
			}
		}) > 0;
	}

	@Override
	@Transactional(readOnly = true)
	public long countInvited(Long userId) {
		return userRepository.count(new Specification<User>() {

			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				return cb.equal(root.get("invitorId"), userId);
			}
		});
	}

	@Override
	@Transactional
	public User get(Long id) {
		return userRepository.findOne(id);
	}

}
